#include "pluginmanager.h"
#include "pluginprocess.h"

#include <QProcess>
#include <QStringList>
#include <QDebug>
#include <QDir>
#include <QDomDocument>

// for now - change this depending on your platofrm - eventually there needs to be a system-wide config file with
// this sort of stuff in it:
//
// Even better - we can get QMake to check for the presence of python and set a preprocessor directive for us.
//
// Even even more betterer: this should be set in the config for this tool, and the default should be the above.
#ifdef Q_OS_LINUX
#define PYTHONPATH "/usr/bin/python"
#else
#define PYTHONPATH "C:/Python/python.exe"
#endif

QString CPluginManager::getLibDir() const
{
    return m_strLibDir;
}

void CPluginManager::setLibDir(const QString &strLibDir)
{
    m_strLibDir = strLibDir;
}

QString CPluginManager::getPluginDir() const
{
    return m_strPluginDir;
}

void CPluginManager::setPluginDir(const QString &strPluginDir)
{
    m_strPluginDir = strPluginDir;
}

void CPluginManager::scanPlugins()
{
    // scan plugins uses the python lib code to get an XML document containing all the information required to list the plugins.
	
    // create the QProcess to run the python code:
    // we need to set the PYTHONPATH environment variable to be the directory that contains our module helper
    // library.
    QProcess proc;
    QStringList env;
    env << QString("PYTHONPATH=%1").arg(m_strLibDir);
    proc.setEnvironment(env);


    // get the python interpreter:
    QString strPythonPath(PYTHONPATH);
    // create command line arguments:
    QStringList args;

    // check that the lib directory exists in debug builds:
    QDir libDir(m_strLibDir);
    Q_ASSERT(libDir.exists());

    args << libDir.absoluteFilePath("pluginManager.py") << "--printConfig" << m_strPluginDir;


    proc.start(strPythonPath, args);
    if (! proc.waitForFinished())
    {
	    Q_ASSERT_X(0, Q_FUNC_INFO, "Could not run python lib code");
	    return;
    }

    QString strDoc = proc.readAllStandardOutput();
    QDomDocument pluginDoc;
    QString strError;
    int nErrorLine, nErrorCol;

    if (!pluginDoc.setContent(strDoc, &strError, &nErrorLine, &nErrorCol))
    {
	qDebug() << "Error:" << strError << nErrorLine << nErrorCol;
	qDebug() << "stdout was:" << strDoc;
	qDebug() << "stderr was:" << proc.readAllStandardError();
    }

	m_pluginConfig = pluginDoc;
    QDomElement docElem = pluginDoc.documentElement();
    QDomNodeList plugins = docElem.elementsByTagName("plugin");

    qDebug() << "Found" << plugins.size() << "plugins:";
    for (int i = 0; i < plugins.size(); i++)
    {
	addPlugin(plugins.at(i).toElement());
    }
}

CPluginProcess *CPluginManager::runScannerPlugins(const QString &strInputFilePath, const QStringList &slPluginNames, const QString &strConfigFile )
{
    // make new plugin object:
	CPluginProcess *plug = new CPluginProcess(this);

    QStringList env;
    env << QString("PYTHONPATH=%1").arg(m_strLibDir);
    plug->setEnvironment(env);


    // get the python interpreter:
    QString strPythonPath(PYTHONPATH);
    // create command line arguments:
    QStringList args;

    // check that the lib directory exists in debug builds:
    QDir libDir(m_strLibDir);
    Q_ASSERT(libDir.exists());

    args << libDir.absoluteFilePath("pluginManager.py")
	    << "--runPlugins"
		<< QString("%1").arg(slPluginNames.join(","))
	    << strInputFilePath
		<< strConfigFile
		<< m_strPluginDir;


    plug->start(strPythonPath, args);

    return plug;
}

void CPluginManager::addPlugin(const QDomElement &pluginXML)
{
    // TODO - this is very cheesy - perhaps clean it up later?
    QString strName = pluginXML.firstChildElement("name").text().trimmed();
    QString strDesc = pluginXML.firstChildElement("description").text().trimmed();
    QString strType = pluginXML.firstChildElement("type").text().trimmed();

    m_pluginDetails[strName] = QPair<QString,QString>(strDesc, strType);

    qDebug() << "Plugin details: " << strName << strType << strDesc;
}

QString CPluginManager::getPluginDescription(const QString &strPluginName) const
{
    if (m_pluginDetails.contains(strPluginName))
    {
	return m_pluginDetails[strPluginName].first;
    }
    return QString();
}

QString CPluginManager::getPluginType(const QString &strPluginName) const
{
    if (m_pluginDetails.contains(strPluginName))
    {
	return m_pluginDetails[strPluginName].second;
    }
    return QString();
}

CPluginManager::CPluginManager()
{
}

CPluginManager * CPluginManager::getPluginManager()
{
	static CPluginManager pm;
	return &pm;
}

QString CPluginManager::getPluginConfig() const
{
	return m_pluginConfig.toString();
}
